import os
import pandas as pd

from typing import Dict, List, Optional
from portfolio_trader.engine.asset_manager import AssetManager
from portfolio_trader.datafeed.data_loader import PortfolioDataLoader
from datetime import datetime, timedelta
from vnpy.trader.constant import Exchange

class PositionManager:
    """持仓管理器
    负责管理用户的持仓信息，并与资产管理引擎协作更新资产状态。
    """

    def __init__(self, asset_manager: AssetManager, data_loader: Optional[PortfolioDataLoader] = None):
        """构造函数"""
        self.asset_manager = asset_manager
        self.positions: Dict[str, Dict] = {}  # 持仓信息
        self.data_loader = data_loader or PortfolioDataLoader()

    def update_market_data(self):
        """更新市场数据"""
        current_time = datetime.now()
        total_daily_pnl = 0.0
        for symbol in self.positions:
            # 更新本地数据
            self.data_loader.update_daily_data(symbol, current_time)

            # 从本地存储获取数据
            position = self.positions[symbol]
            csv_path = os.path.join(self.data_loader.storage.data_path, f"{symbol}_daily.csv")
            df = pd.read_csv(csv_path)
            if df.empty:
                continue
                
            df["datetime"] = pd.to_datetime(df["datetime"])
            df = df.sort_values("datetime", ascending=False)
            
            # 获取最新价格和前一天价格
            current_price = df.iloc[0]["close_price"]
            prev_price = df.iloc[1]["close_price"] if len(df) > 1 else position["cost"]
            print(f"当前价格{current_price}, 昨天价格{prev_price}")
            # 更新持仓信息
            position["current_price"] = current_price
            cost = position["cost"]
            volume = position["volume"]
            market_value = current_price * volume
            
            position["available"] = position["volume"]  # 过了一天 全部持仓可用
            position["market_value"] = market_value
            position["pnl"] = (current_price - cost) * volume
            position["pnl_pct"] = ((current_price - cost) / cost) * 100
            
            position["daily_pnl"] = (current_price - prev_price) * volume
            position["daily_pnl_pct"] = ((current_price - prev_price) / prev_price) * 100
            total_daily_pnl += position["daily_pnl"]
        
        # 更新资产管理器中的日盈亏
        self.asset_manager.update_daily_pnl(total_daily_pnl)

    def get_current_price(self, symbol: str) -> float:
        """获取股票最新价格"""
        bar = self.data_loader.get_latest_daily_data(symbol)
        
        if not bar or bar == None:
            print(f"获取{symbol}最新数据失败")  # 打印错误信息
            return 0.0
        
        return bar.close_price

    def buy(self, symbol: str, price: float, volume: int, commission_rate: float = 0.0001) -> str:
        """买入股票
        :param commission_rate: 手续费率，默认万分之一
        """
        current_price = self.get_current_price(symbol)
        if current_price == 0.0:
            print(f"获取{symbol}价格失败")  # 打印错误信息
            return "Cannot get current price"  # 返回错误信息

        cost = price * volume  # 使用传入的价格计算成本
        commission = cost * commission_rate
        total_cost = cost + commission
        if not self.asset_manager.buy(total_cost):
            print(f"购买{symbol}失败，资金不足")  # 打印错误信息
            return "NoEnoughMoney"

        # 获取股票名称
        stock_name = self.data_loader.get_stock_name(symbol)
        exchange_code = self.data_loader._get_exchange(symbol)
        # 更新持仓
        if symbol in self.positions:
            old_cost = self.positions[symbol]["cost"] * self.positions[symbol]["volume"]
            new_cost = old_cost + cost
            self.positions[symbol]["volume"] += volume
            self.positions[symbol]["cost"] = new_cost / self.positions[symbol]["volume"]
            self.positions[symbol]["current_price"] = current_price
            self.positions[symbol]["market_value"] = self.positions[symbol]["volume"] * current_price
            self.positions[symbol]["pnl"] = self.positions[symbol]["market_value"] - new_cost
            self.positions[symbol]["pnl_pct"] = (self.positions[symbol]["market_value"] - new_cost) / new_cost * 100
            self.positions[symbol]["daily_pnl"] = (current_price - self.positions[symbol]["current_price"]) * volume
            self.positions[symbol]["daily_pnl_pct"] = (current_price - self.positions[symbol]["current_price"]) / self.positions[symbol]["current_price"] * 100
        else:
            self.positions[symbol] = {
                "volume": volume,                       # 股票持仓
                "available": 0,                         # 可用数量
                "cost": price,                          # 成本价                  
                "current_price": current_price,         # 当前价格
                "market_value": volume * current_price, # 市值
                "pnl": 0.0,                             # 盈亏  
                "pnl_pct": 0.0,                         # 盈亏百分比    
                "daily_pnl": 0.0,                       # 日盈亏
                "daily_pnl_pct": 0.0,                   # 日盈亏百分比
                "name": stock_name,                     # 股票名称
                "exchange": exchange_code,              # 交易所代码
            }

        # 更新资产
        self.update_asset()
        return "Success"

    def sell(self, symbol: str, price: float, volume: int, commission_rate: float = 0.0001) -> bool:
        """卖出股票
        :param commission_rate: 手续费率，默认万分之一
        """
        if symbol not in self.positions or self.positions[symbol]["volume"] < volume:
            return False

        # 计算收入
        income = price * volume
        commission = income * commission_rate
        net_income = income - commission
        self.asset_manager.sell(net_income)

        # 更新持仓
        self.positions[symbol]["volume"] -= volume
        if self.positions[symbol]["volume"] == 0:
            del self.positions[symbol]

        # 更新资产
        self.update_asset()
        return True

    def update_asset(self) -> None:
        """更新资产状态"""
        market_value = 0.0
        for pos in self.positions.values():
            market_value += pos["market_value"]

        self.asset_manager.update_position_value(market_value)

    def get_position(self, symbol: str) -> Optional[Dict]:
        """获取持仓信息"""
        return self.positions.get(symbol)

    def get_positions(self) -> Dict:
        """获取所有持仓"""
        return self.positions
        
    def save_data(self) -> Dict:
        """返回Json序列化后的持仓数据"""
        # 序列化Exchange枚举值为字符串
        serialized_positions = {}
        for symbol, pos in self.positions.items():
            serialized_pos = pos.copy()
            if isinstance(serialized_pos["exchange"], Exchange):
                serialized_pos["exchange"] = serialized_pos["exchange"].value
            serialized_positions[symbol] = serialized_pos
            
        return serialized_positions.copy()
        
    def load_data(self, data: Dict) -> None:
        """加载持仓数据"""    
        # 反序列化Exchange字符串为枚举值
        for symbol, pos in data.items():
            if isinstance(pos.get("exchange"), str):
                pos["exchange"] = Exchange(pos["exchange"])
                
        self.positions = data
